#include <iostream>
#include <cstdlib>
#include <vector>

using namespace std;

template<class T> class exp {
public:
	virtual T executa() const = 0;
};

template<class T> class var : public exp<T> {
private:
	T v;
public:
	var() {
	}
	var(T v) :
		v(v) {
	}
	virtual T executa() const {
		return v;
	}
	var<T>& operator =(T _v) {
		v = _v;
		return *this;
	}
};

template<class T> class cte : public exp<T> {
private:
	T v;
public:
	cte(const T v) :
		v(v) {
	}
	virtual T executa() const {
		return v;
	}
};

/*
 class cteInt: public cte<int> {
 public:
 cteInt(const int n):cte<int>(n){}
 };*/

template<class T> class soma : public exp<T> {
private:
	const exp<T> *a, *b;
public:
	soma(const exp<T> * a, const exp<T> * b) :
		a(a), b(b) {
	}
	virtual T executa() const {
		return a->executa() + b->executa();
	}
};

template<class T> class multiplica : public exp<T> {
private:
	const exp<T> *a, *b;
public:
	multiplica(const exp<T> * a, const exp<T> * b) :
		a(a), b(b) {
	}
	virtual T executa() const {
		return a->executa() * b->executa();
	}
};

template<class T> class modulo : public exp<T> {
private:
	const exp<T> *a, *b;
public:
	modulo(const exp<T> * a, const exp<T> * b) :
		a(a), b(b) {
	}
	virtual T executa() const {
		return a->executa() % b->executa();
	}
};

template<class T> class igual : public exp<bool> {
private:
	const exp<T> *a, *b;
public:
	igual(const exp<T> * a, const exp<T> * b) :
		a(a), b(b) {
	}
	virtual bool executa() const {
		return a->executa() == b->executa();
	}
};

template<class T> class maior : public exp<bool> {
private:
	const exp<T> *a, *b;
public:
	maior(const exp<T> * a, const exp<T> * b) :
		a(a), b(b) {
	}
	virtual bool executa() const {
		return a->executa() > b->executa();
	}
};

template<class T> class maiorIgual : public exp<bool> {
private:
	const exp<T> *a, *b;
public:
	maiorIgual(const exp<T> * a, const exp<T> * b) :
		a(a), b(b) {
	}
	virtual bool executa() const {
		return a->executa() >= b->executa();
	}
};

class _and : public exp<bool> {
private:
	const exp<bool> *a, *b;
public:
	_and(const exp<bool> * a, const exp<bool> * b) :
		a(a), b(b) {
	}
	virtual bool executa() const {
		return a->executa() && b->executa();
	}
};

class _or : public exp<bool> {
private:
	const exp<bool> *a, *b;
public:
	_or(const exp<bool> * a, const exp<bool> * b) :
		a(a), b(b) {
	}
	virtual bool executa() const {
		return a->executa() || b->executa();
	}
};

_and operator &&(const exp<bool>& a, const exp<bool>& b) {
	return _and(&a, &b);
}

_or operator ||(const exp<bool>& a, const exp<bool>& b) {
	return _or(&a, &b);
}

template<class T> igual<T> operator ==(const exp<T>& a, const exp<T>& b) {
	return igual<T>(&a, &b);
}

template<class T> maior<T> operator >(const exp<T>& a, const exp<T>& b) {
	return maior<T>(&a, &b);
}

template<class T> maior<T> operator <(const exp<T>& a, const exp<T>& b) {
	return maior<T>(&b, &a);
}

template<class T> maiorIgual<T> operator >=(const exp<T>& a, const exp<T>& b) {
	return maiorIgual<T>(&a, &b);
}

template<class T> maiorIgual<T> operator <=(const exp<T>& a, const exp<T>& b) {
	return maiorIgual<T>(&b, &a);
}

template<class T> modulo<T> operator %(const exp<T>& a, const exp<T>& b) {
	return modulo<T>(&a, &b);
}

template<class T> soma<T> operator +(const exp<T>& a, const exp<T>& b) {
	return soma<T>(&a, &b);
}

template<class T> multiplica<T> operator *(const exp<T>& a, const exp<T>& b) {
	return multiplica<T>(&a, &b);
}

vector<int> I(int a, int b) {
	vector<int> l;
	for (int i = a; i <= b; i ++)
		l.push_back(i );
	return l;
}

template<class T> vector<T> I(T a, T b) {
	vector<T> l;
	l.push_back(a);
	l.push_back(b);
	return l;
}

template<class T> vector<T> apply(var<T>& x, const vector<T>& v, const exp<T>& e) {
	return apply(x,v,e,var<bool>(true));
}

template<class T> vector<T> apply(var<T>& x, const vector<T>& v, const exp<T>& e, const exp<bool>& check) {
	vector<T> result;
	for (typename vector<T>::const_iterator i = v.begin(); i != v.end(); ++i ) {
		x = *i;
		if (check.executa()) {
			result.push_back(e.executa());
		}
	}
	return result;
}

template<class T> ostream& operator <<(ostream& o, const vector<T>& v) {
	for (typename vector<T>::const_iterator i = v.begin(); i != v.end(); ++i )
		o << *i << " ";
	return o;
}

template <class T>
struct C1 {
	vector<T> l;
	C1(const vector<T>& l) :
		l(l) {
	}
};

template <class T>
struct C2 {
	vector<T> l;
	var<T>& x;
	C2(var<T>& x, const vector<T>& l) :
		x(x), l(l) {
	}
};

template <class T>
struct C3 {
	vector<T> l;
	var<T>& x;
	const exp<T>& e;
	C3(const exp<T>& e, var<T>& x, const vector<T>& l) :
		e(e), x(x), l(l) {
	}
};

template <class T>
struct C4 {
	vector<T> l;
	var<T>& x;
	const exp<T>& e;
	const exp<bool>& check;
	C4(const exp<T>& e, var<T>& x, const vector<T>& l, const exp<bool>& check) :
		e(e), x(x), l(l), check(check) {
	}
};

template <class T>
C1<T> operator -(const vector<T>& l) {
	return C1<T>(l );
}

template <class T>
C2<T> operator <(var<T>& x, const C1<T>& c1) {
	return C2<T>(x, c1.l);
}

template <class T>
C3<T> operator |(const exp<T>& e, const C2<T>& c) {
	return C3<T>(e, c.x, c.l);
}

template <class T>
C4<T> operator |(const C3<T>& c, const exp<bool>& check) {
	return C4<T>(c.e, c.x, c.l,check);
}

/*struct ZF {
	template <class T>
	vector<T> operator [](const C4<T>& c) {
		return apply(c.x, c.l, c.e, c.check);
	}
	template <class T>
	vector<T> operator [](const C3<T>& c) {
		return apply(c.x, c.l, c.e, cte<bool>(true));
	}	
}zf;*/

template<class T> vector<T> zf(const exp<T>& e, const C2<T>& c) {
	return zf(e,c,true);
}

template<class T> vector<T> zf(const exp<T>& e, const C2<T>& c, const exp<bool>& check) {
	return apply(c.x,c.l,e,check);
}

/*
int main(void) {
	//cout << (x * x, x <- I[0..10])
	var<int> x = 0;
	var<int> y(2);
	cout << apply(x, I(0, 10), x*x) << endl;
	cout << zf( x*x  , x <- I(0,10) , x%y == cte<int>(0)) << endl;
	cout << zf( x*x  , x <- I(0,10) , x > y) << endl;
	cout << zf( x*x  , x <- I(0,10) , (x > y) && (y > x)) << endl;
	cout << zf( x*x  , x <- I(0,10) , (x > y) || (y > x)) << endl;	
	system("pause");
	return EXIT_SUCCESS;
}*/
